#include "csgunionnode.h"
#include "csgprimitivenode.h"

CSGUnionNode::CSGUnionNode(Expression &e1, Expression &e2)
    :CSGNode(0)
{
    addChild(new CSGPrimitiveNode(e1, this));
    addChild(new CSGPrimitiveNode(e2, this));
}

CSGUnionNode::CSGUnionNode(Expression &e, CSGNode *right)
    :CSGNode(0)
{
    addChild(new CSGPrimitiveNode(e, this));
    addChild(right);
}

CSGUnionNode::CSGUnionNode(CSGNode *left, Expression &e)
    :CSGNode(0)
{
    addChild(left);
    addChild(new CSGPrimitiveNode(e, this));
}

CSGUnionNode::CSGUnionNode(CSGNode *left, CSGNode *right)
    :CSGNode(0)
{
    addChild(left);
    addChild(right);
}

double CSGUnionNode::eval(double x, double y, double z)
{
    return std::min(((CSGNode*)getChild(0))->eval(x,y,z), ((CSGNode*)getChild(1))->eval(x,y,z));
}

bool CSGUnionNode::emptyTest(StarTestBox *box)
{
    bool boundary = false;

    for (int i = 0; i < getNumChild(); i++)
    {
        ((CSGNode*)getChild(i))->emptyTest(box);

        if (box->isInner())
        {
            break;
        }
        else if (box->isBoundary())
        {
            boundary = true;
        }
    }

    if (!box->isInner() && boundary)
    {
        box->pos = BOX_BOUNDARY;
    }

    return box->isOuter();
}

bool CSGUnionNode::starTest(StarTestBox *box, double *pt)
{
    bool count = 0;
    for (int i = 0; i < getNumChild(); i++)
    {
        box->pos = BOX_UNKNOWN;
        if (!((CSGNode*)getChild(i))->starTest(box, pt) && !box->isOuter())
        {
            count = 0;
            break;
        }

        if (box->pos == BOX_STAR)
        {
            count++;
        }
    }

    if (count > 0)
    {
        box->pos = BOX_STAR;
    }

    return box->isStar();
}

bool CSGUnionNode::complementStarTest(StarTestBox *box, double *pt)
{
    for (int i = 0; i < getNumChild(); i++)
    {
        box->pos = BOX_UNKNOWN;
        if (!((CSGNode*)getChild(i))->complementStarTest(box, pt))
        {
            break;
        }
    }

    return box->isStar();
}

bool CSGUnionNode::ptInSet(double *pt)
{
    for (int i = 0; i < getNumChild(); i++)
    {
        if (((CSGNode*)getChild(i))->ptInSet(pt))
        {
            return true;
        }
    }

    return false;
}
